package com.zatech.cgnci.project.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zatech.cgnci.project.base.context.UserContext;
import com.zatech.cgnci.project.base.enums.ClaimTaskStatusEnum;
import com.zatech.cgnci.project.base.enums.ResponseCodeEnum;
import com.zatech.cgnci.project.base.exception.GlobalException;
import com.zatech.cgnci.project.base.utils.ConvertUtils;
import com.zatech.cgnci.project.base.utils.DateUtils;
import com.zatech.cgnci.project.base.utils.VerifyUtils;
import com.zatech.cgnci.project.dto.CgnciApprovalConfigAuthQueryDTO;
import com.zatech.cgnci.project.dto.CgnciApprovalConfigAuthUserDTO;
import com.zatech.cgnci.project.dto.CgnciApprovalConfigRoleUserDTO;
import com.zatech.cgnci.project.entity.*;
import com.zatech.cgnci.project.mapper.CgnciApprovalConfigRoleUserMapper;
import com.zatech.cgnci.project.service.CgnciApprovalConfigRoleUserService;
import com.zatech.cgnci.project.service.CgnciApprovalInfoService;
import com.zatech.cgnci.project.service.CgnciClaimCaseService;
import com.zatech.cgnci.project.vo.CgnciApprovalConfigRoleUserVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 审批流程节点规则配置角色用户表 服务实现类
 * </p>
 *
 * @author Generator
 * @since 2025-02-12
 */
@Slf4j
@Service
public class CgnciApprovalConfigRoleUserServiceImpl extends ServiceImpl<CgnciApprovalConfigRoleUserMapper, CgnciApprovalConfigRoleUserDO> implements CgnciApprovalConfigRoleUserService {

    @Resource
    private CgnciApprovalInfoService approvalInfoService;

    @Resource
    private CgnciClaimCaseService claimCaseService;

    private final static List<String> TASK_TYPES = Arrays.asList("新增险种最大净自留限额任务", "编辑险种最大净自留限额任务",
            "新增再保公司审核任务", "编辑再保公司审核任务", "新建项目任务", "作废项目任务",
            "保单录入任务", "分入合约录入任务", "分入合约批改任务", "保单批改任务",
            "分出合约录入任务", "分出合约批改任务");

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveOrUpdateApprovalUser(CgnciApprovalConfigRoleUserDTO roleUserDTOList) {
        // 获取当前登录用户
        UserEntity user = UserContext.getUser();
        String taskType = roleUserDTOList.getTaskType();
        String currentApproverNode = roleUserDTOList.getCurrentApproverNode();
        List<CgnciApprovalConfigRoleUserDTO.RoleUserDTO> list = roleUserDTOList.getRoleUserDTOList();
        List<CgnciApprovalConfigRoleUserDO> roleUserDOList = ConvertUtils.convert(list, CgnciApprovalConfigRoleUserDO.class);
        roleUserDOList.forEach(roleUser -> {
            Long roleUserId = roleUser.getRoleUserId();
            // 查询当前用户在当前业务类型和当前处理人结点是否存在
            CgnciApprovalConfigRoleUserDO userDO = this.getOne(new LambdaQueryWrapper<CgnciApprovalConfigRoleUserDO>()
                    .eq(CgnciApprovalConfigRoleUserDO::getTaskType, taskType)
                    .eq(CgnciApprovalConfigRoleUserDO::getCurrentApproverNode, currentApproverNode)
                    .eq(CgnciApprovalConfigRoleUserDO::getCurrentApprover, roleUser.getCurrentApprover())
                    .eq(CgnciApprovalConfigRoleUserDO::getCurrentApproverName, roleUser.getCurrentApproverName()));
            if (VerifyUtils.isNotEmpty(userDO) && VerifyUtils.isEmpty(roleUserId)) {
                throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR, "当前账号:{" + userDO.getCurrentApproverName() + "-" + userDO.getCurrentApprover() + "}已有审批权限");
            }
            roleUser.setTaskType(roleUserDTOList.getTaskType());
            roleUser.setTaskTypeCode(roleUserDTOList.getTaskTypeCode());
            roleUser.setCurrentApproverNode(roleUserDTOList.getCurrentApproverNode());
            if (VerifyUtils.isEmpty(roleUserId)) {
                roleUser.setCreateUser(user.getNameAndCode());
            }
            roleUser.setUpdateUser(user.getNameAndCode());
            this.saveOrUpdate(roleUser);
        });
    }

    @Override
    public List<CgnciApprovalConfigRoleUserDO> listCreateUser(String taskType, String currentApproverNode, String usercode) {
        return this.list(new LambdaQueryWrapper<CgnciApprovalConfigRoleUserDO>()
                .eq(CgnciApprovalConfigRoleUserDO::getTaskType, taskType)
                .eq(CgnciApprovalConfigRoleUserDO::getCurrentApproverNode, currentApproverNode)
                .eq(CgnciApprovalConfigRoleUserDO::getAuthCode, usercode)
                .le(CgnciApprovalConfigRoleUserDO::getStartDate, DateUtils.dateToString(new Date(), DateUtils.FORMAT_3))// start_date <= target_date
                .ge(CgnciApprovalConfigRoleUserDO::getEndDate, DateUtils.dateToString(new Date(), DateUtils.FORMAT_3)));// end_date >= target_date
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void recycleAuthUser(CgnciApprovalConfigRoleUserDO recycleAuthUser) {
        // 当前处理节点
        String node = recycleAuthUser.getCurrentApproverNode();
        if ("发起人".equals(node)) {
            // 判断回收任务是否在列表内
            if (TASK_TYPES.contains(recycleAuthUser.getTaskType())) {
                // 查询授权发起人的当前任务中有代理人的任务
                List<CgnciApprovalInfoDO> agentList = approvalInfoService.list(new LambdaQueryWrapper<CgnciApprovalInfoDO>()
                        .eq(CgnciApprovalInfoDO::getFounderId, recycleAuthUser.getAuthCode())
                        .eq(CgnciApprovalInfoDO::getTaskType, recycleAuthUser.getTaskType())
                        .like(CgnciApprovalInfoDO::getCurrentAgentAndName, recycleAuthUser.getCurrentApprover()));
                if (VerifyUtils.isEmpty(agentList)) {
                    // 删除授权记录
                    this.removeById(recycleAuthUser.getRoleUserId());
                    return;
                }
                agentList.forEach(agent -> {
                    // 处理代理人
                    String currentAgentAndName = agent.getCurrentAgentAndName();
                    // 剔除掉当前代理人
                    List<String> currentAgentAndNameList = new ArrayList<>(Arrays.asList(currentAgentAndName.split(",")));
                    currentAgentAndNameList.remove(recycleAuthUser.getCurrentApproverName() + "-" + recycleAuthUser.getCurrentApprover());
                    String updateCurrentAgentAndName = String.join(",", currentAgentAndNameList);

                    // 更新代理人
                    LambdaUpdateWrapper<CgnciApprovalInfoDO> updateWrapper = Wrappers.lambdaUpdate();
                    updateWrapper.eq(CgnciApprovalInfoDO::getApprovalInfoId, agent.getApprovalInfoId());
                    updateWrapper.set(CgnciApprovalInfoDO::getCurrentAgentAndName, VerifyUtils.isEmpty(updateCurrentAgentAndName) ? null : updateCurrentAgentAndName);
                    approvalInfoService.update(updateWrapper);

                });
            } else {
                // 先查询所有理赔任务中发起人配置代理人的任务列表
                List<CgnciApprovalConfigRoleUserDO> claimAgentList = this.list(new LambdaQueryWrapper<CgnciApprovalConfigRoleUserDO>()
                        .like(CgnciApprovalConfigRoleUserDO::getAuthCode, recycleAuthUser.getAuthCode())
                        .like(CgnciApprovalConfigRoleUserDO::getCurrentApprover, recycleAuthUser.getCurrentApprover()));
                if (VerifyUtils.isEmpty(claimAgentList)) {
                    this.removeById(recycleAuthUser.getRoleUserId());
                    return;
                }
                // 根据任务类型去重得到一个数量
                List<CgnciApprovalConfigRoleUserDO> uniqueRoleUser = claimAgentList.stream()
                        .collect(Collectors.collectingAndThen(
                                Collectors.toMap(CgnciApprovalConfigRoleUserDO::getTaskType, roleUser -> roleUser, (existing, replacement) -> existing),
                                map -> new ArrayList<>(map.values())));
                if (uniqueRoleUser.size() == 1) {
                    // 查询理赔案件主表
                    List<CgnciClaimCaseDO> claimCurrentAgentList = claimCaseService.list(new LambdaQueryWrapper<CgnciClaimCaseDO>()
                            .like(CgnciClaimCaseDO::getCreator, recycleAuthUser.getAuthCode())
                            .like(CgnciClaimCaseDO::getCurrentAgentAndName, recycleAuthUser.getCurrentApprover()));
                    if (VerifyUtils.isEmpty(claimCurrentAgentList)) {
                        this.removeById(recycleAuthUser.getRoleUserId());
                        return;
                    }
                    claimCurrentAgentList.forEach(agent -> {
                        // 处理代理人
                        String currentAgentAndName = agent.getCurrentAgentAndName();
                        // 剔除掉当前代理人
                        List<String> currentAgentAndNameList = new ArrayList<>(Arrays.asList(currentAgentAndName.split(",")));
                        currentAgentAndNameList.remove(recycleAuthUser.getCurrentApproverName() + "-" + recycleAuthUser.getCurrentApprover());
                        String updateCurrentAgentAndName = String.join(",", currentAgentAndNameList);

                        // 更新代理人
                        LambdaUpdateWrapper<CgnciClaimCaseDO> updateWrapper = Wrappers.lambdaUpdate();
                        updateWrapper.eq(CgnciClaimCaseDO::getCaseId, agent.getCaseId());
                        updateWrapper.set(CgnciClaimCaseDO::getCurrentAgentAndName, VerifyUtils.isEmpty(updateCurrentAgentAndName) ? null : updateCurrentAgentAndName);
                        claimCaseService.update(updateWrapper);
                    });
                }
            }
        } else {
            // 不是发起人授权的情况下，只需要处理审批中任务的的当前处理人
            // 查询授权发起人的当前任务中有代理人的任务
            List<CgnciApprovalInfoDO> approvalAgentList = approvalInfoService.list(new LambdaQueryWrapper<CgnciApprovalInfoDO>()
                    .eq(CgnciApprovalInfoDO::getTaskType, recycleAuthUser.getTaskType())
                    .eq(CgnciApprovalInfoDO::getCurrentApproverNode, recycleAuthUser.getCurrentApproverNode())
                    .like(CgnciApprovalInfoDO::getCurrentApproverAndName, recycleAuthUser.getAuthCode())
                    .like(CgnciApprovalInfoDO::getCurrentApproverAndName, recycleAuthUser.getCurrentApprover())
                    .eq(CgnciApprovalInfoDO::getStatus, "1"));
            if (VerifyUtils.isEmpty(approvalAgentList)) {
                // 删除授权记录
                this.removeById(recycleAuthUser.getRoleUserId());
                return;
            }

            approvalAgentList.forEach(approvalAgent -> {
                // 处理当前处理人
                String approvalAndName = approvalAgent.getCurrentApproverAndName();
                // 剔除掉当前代理人
                List<String> approvalAndNameList = new ArrayList<>(Arrays.asList(approvalAndName.split(",")));
                approvalAndNameList.remove(recycleAuthUser.getCurrentApproverName() + "-" + recycleAuthUser.getCurrentApprover());
                String updateApprovalAndName = String.join(",", approvalAndNameList);

                // 更新代理人
                LambdaUpdateWrapper<CgnciApprovalInfoDO> updateWrapper = Wrappers.lambdaUpdate();
                updateWrapper.eq(CgnciApprovalInfoDO::getApprovalInfoId, approvalAgent.getApprovalInfoId());
                updateWrapper.set(CgnciApprovalInfoDO::getCurrentApproverAndName, VerifyUtils.isEmpty(updateApprovalAndName) ? null : updateApprovalAndName);
                approvalInfoService.update(updateWrapper);

            });

        }
        // 删除授权记录
        this.removeById(recycleAuthUser.getRoleUserId());
    }


    @Override
    public void grantAuthUser(CgnciApprovalConfigRoleUserDO recycleAuthUser) {
        // 当前处理节点
        String node = recycleAuthUser.getCurrentApproverNode();
        if ("发起人".equals(node)) {
            // 判断授权任务是否在列表内
            if (TASK_TYPES.contains(recycleAuthUser.getTaskType())) {
                // 查询发起人的当前任务列表
                List<CgnciApprovalInfoDO> founderList = approvalInfoService.list(new LambdaQueryWrapper<CgnciApprovalInfoDO>()
                        .eq(CgnciApprovalInfoDO::getFounderId, recycleAuthUser.getAuthCode())
                        .eq(CgnciApprovalInfoDO::getTaskType, recycleAuthUser.getTaskType()));
                if (VerifyUtils.isEmpty(founderList)) {
                    return;
                }
                founderList.forEach(agent -> {
                    // 处理代理人
                    String currentAgentAndName = agent.getCurrentAgentAndName();
                    if (VerifyUtils.isNotEmpty(currentAgentAndName)) {
                        // 先检查代理人是否在当前代理人字段中
                        if (currentAgentAndName.contains(recycleAuthUser.getCurrentApproverName() + "-" + recycleAuthUser.getCurrentApprover())) {
                            return;
                        }

                        // 添加当前代理人
                        List<String> currentAgentAndNameList = new ArrayList<>(Arrays.asList(currentAgentAndName.split(",")));
                        currentAgentAndNameList.add(recycleAuthUser.getCurrentApproverName() + "-" + recycleAuthUser.getCurrentApprover());
                        currentAgentAndName = String.join(",", currentAgentAndNameList);
                    } else {
                        currentAgentAndName = recycleAuthUser.getCurrentApproverName() + "-" + recycleAuthUser.getCurrentApprover();
                    }

                    // 更新代理人
                    LambdaUpdateWrapper<CgnciApprovalInfoDO> updateWrapper = Wrappers.lambdaUpdate();
                    updateWrapper.eq(CgnciApprovalInfoDO::getApprovalInfoId, agent.getApprovalInfoId());
                    updateWrapper.set(CgnciApprovalInfoDO::getCurrentAgentAndName, VerifyUtils.isEmpty(currentAgentAndName) ? null : currentAgentAndName);
                    approvalInfoService.update(updateWrapper);

                });
            } else {
                // 查询发起人理赔案件主表
                List<CgnciClaimCaseDO> claimCreatorList = claimCaseService.list(new LambdaQueryWrapper<CgnciClaimCaseDO>()
                        .like(CgnciClaimCaseDO::getCreator, recycleAuthUser.getAuthCode()));
                if (VerifyUtils.isEmpty(claimCreatorList)) {
                    return;
                }
                claimCreatorList.forEach(claimCreator -> {
                    // 处理代理人
                    String currentAgentAndName = claimCreator.getCurrentAgentAndName();
                    if (VerifyUtils.isNotEmpty(currentAgentAndName)) {
                        // 先检查代理人是否在当前代理人字段中
                        if (currentAgentAndName.contains(recycleAuthUser.getCurrentApproverName() + "-" + recycleAuthUser.getCurrentApprover())) {
                            return;
                        }

                        // 添加当前代理人
                        List<String> currentAgentAndNameList = new ArrayList<>(Arrays.asList(currentAgentAndName.split(",")));
                        currentAgentAndNameList.add(recycleAuthUser.getCurrentApproverName() + "-" + recycleAuthUser.getCurrentApprover());
                        currentAgentAndName = String.join(",", currentAgentAndNameList);
                    } else {
                        currentAgentAndName = recycleAuthUser.getCurrentApproverName() + "-" + recycleAuthUser.getCurrentApprover();
                    }
                    // 更新代理人
                    LambdaUpdateWrapper<CgnciClaimCaseDO> updateWrapper = Wrappers.lambdaUpdate();
                    updateWrapper.eq(CgnciClaimCaseDO::getCaseId, claimCreator.getCaseId());
                    updateWrapper.set(CgnciClaimCaseDO::getCurrentAgentAndName, VerifyUtils.isEmpty(currentAgentAndName) ? null : currentAgentAndName);
                    claimCaseService.update(updateWrapper);
                });
            }
        } else {
            // 不是发起人授权的情况下，只需要处理审批中任务的的当前处理人
            // 查询授权发起人的当前任务中的任务
            List<CgnciApprovalInfoDO> approvalAgentList = approvalInfoService.list(new LambdaQueryWrapper<CgnciApprovalInfoDO>()
                    .eq(CgnciApprovalInfoDO::getTaskType, recycleAuthUser.getTaskType())
                    .eq(CgnciApprovalInfoDO::getCurrentApproverNode, recycleAuthUser.getCurrentApproverNode())
                    .like(CgnciApprovalInfoDO::getCurrentApproverAndName, recycleAuthUser.getAuthCode())
                    .eq(CgnciApprovalInfoDO::getStatus, "1"));
            if (VerifyUtils.isEmpty(approvalAgentList)) {
                return;
            }

            approvalAgentList.forEach(approvalAgent -> {
                // 处理当前处理人
                String approvalAndName = approvalAgent.getCurrentApproverAndName();
                // 先检查代理人是否在当前代理人字段中
                if (approvalAndName.contains(recycleAuthUser.getCurrentApproverName() + "-" + recycleAuthUser.getCurrentApprover())) {
                    return;
                }
                // 添加当前代理人
                List<String> currentAgentAndNameList = new ArrayList<>(Arrays.asList(approvalAndName.split(",")));
                currentAgentAndNameList.add(recycleAuthUser.getCurrentApproverName() + "-" + recycleAuthUser.getCurrentApprover());
                approvalAndName = String.join(",", currentAgentAndNameList);

                // 更新代理人
                LambdaUpdateWrapper<CgnciApprovalInfoDO> updateWrapper = Wrappers.lambdaUpdate();
                updateWrapper.eq(CgnciApprovalInfoDO::getApprovalInfoId, approvalAgent.getApprovalInfoId());
                updateWrapper.set(CgnciApprovalInfoDO::getCurrentApproverAndName, VerifyUtils.isEmpty(approvalAndName) ? null : approvalAndName);
                approvalInfoService.update(updateWrapper);
            });
        }
    }

    @Override
    public List<CgnciApprovalConfigRoleUserDO> listApprovalUser(String taskType, String currentApproverNode) {
        List<CgnciApprovalConfigRoleUserDO> result = new ArrayList<>();
        // 查询系统本身配置的审批人
        List<CgnciApprovalConfigRoleUserDO> roleUserDOS = this.list(new LambdaQueryWrapper<CgnciApprovalConfigRoleUserDO>()
                .eq(CgnciApprovalConfigRoleUserDO::getTaskType, taskType)
                .isNull(CgnciApprovalConfigRoleUserDO::getAuthCode)
                .eq(CgnciApprovalConfigRoleUserDO::getCurrentApproverNode, currentApproverNode));
        if (VerifyUtils.isNotEmpty(roleUserDOS)) {
            result.addAll(roleUserDOS);
        }

        // 查询系统本身配置的审批人添加的代理人
        List<CgnciApprovalConfigRoleUserDO> agentRoleUserDOS = this.list(new LambdaQueryWrapper<CgnciApprovalConfigRoleUserDO>()
                .eq(CgnciApprovalConfigRoleUserDO::getTaskType, taskType)
                .isNotNull(CgnciApprovalConfigRoleUserDO::getAuthCode)
                .eq(CgnciApprovalConfigRoleUserDO::getCurrentApproverNode, currentApproverNode)
                .le(CgnciApprovalConfigRoleUserDO::getStartDate, DateUtils.dateToString(new Date(), DateUtils.FORMAT_3))// start_date <= target_date
                .ge(CgnciApprovalConfigRoleUserDO::getEndDate, DateUtils.dateToString(new Date(), DateUtils.FORMAT_3)));// end_date >= target_date
        if (VerifyUtils.isNotEmpty(agentRoleUserDOS)) {
            result.addAll(agentRoleUserDOS);
        }

        return result;
    }

    @Override
    public List<CgnciApprovalConfigRoleUserVO> listFlowTask(String username, String usercode) {
        return this.baseMapper.listFlowTask(username, usercode);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveAuthorizedUser(CgnciApprovalConfigAuthUserDTO authUserDTO) {
        // 获取当前登录用户
        UserEntity user = UserContext.getUser();
        List<CgnciApprovalConfigAuthUserDTO.ConfigType> configTypes = authUserDTO.getConfigTypes();
        configTypes.forEach(configType -> {
            if (user.getUsercode().equals(authUserDTO.getCurrentApprover())) {
                log.warn("无需授权给自己");
                return;
            }

            // 查询当前用户在该任务流程具有哪些审批节点权限
            List<CgnciApprovalConfigRoleUserDO> nodes = this.list(new LambdaQueryWrapper<CgnciApprovalConfigRoleUserDO>()
                    .eq(CgnciApprovalConfigRoleUserDO::getTaskType, configType.getTaskType())
                    .eq(CgnciApprovalConfigRoleUserDO::getCurrentApprover, user.getUsercode())
                    .eq(CgnciApprovalConfigRoleUserDO::getCurrentApproverName, user.getUsername()));
            if (VerifyUtils.isEmpty(nodes)) {
                log.warn("当前用户在该任务流程没有审批节点权限");
                return;
            }

            // 遍历当前用户具有审批的节点，全部授权给代理人
            nodes.forEach(node -> {
                // 查询被授权的用户是否在授权用户所在的当前业务流程的当前结点中
                CgnciApprovalConfigRoleUserDO userDO = this.getOne(new LambdaQueryWrapper<CgnciApprovalConfigRoleUserDO>()
                        .eq(CgnciApprovalConfigRoleUserDO::getTaskType, configType.getTaskType())
                        .eq(CgnciApprovalConfigRoleUserDO::getCurrentApproverNode, node.getCurrentApproverNode())
                        .eq(CgnciApprovalConfigRoleUserDO::getCurrentApprover, authUserDTO.getCurrentApprover())
                        .eq(CgnciApprovalConfigRoleUserDO::getAuthCode, user.getUsercode()));
                if (VerifyUtils.isNotEmpty(userDO)) {
                    // 更新时间段和备注
                    userDO.setStartDate(authUserDTO.getStartDate());
                    userDO.setEndDate(authUserDTO.getEndDate());
                    userDO.setRemark(authUserDTO.getRemark());
                    this.updateById(userDO);
                    return;
                }
                CgnciApprovalConfigRoleUserDO saveUser = ConvertUtils.convert(authUserDTO, CgnciApprovalConfigRoleUserDO.class);
                saveUser.setTaskType(configType.getTaskType());
                saveUser.setTaskTypeCode(configType.getTaskTypeCode());
                saveUser.setAuthName(user.getUsername());
                saveUser.setAuthCode(user.getUsercode());
                saveUser.setCurrentApproverNode(node.getCurrentApproverNode());
                saveUser.setCreateUser(user.getNameAndCode());
                saveUser.setUpdateUser(user.getNameAndCode());
                this.save(saveUser);


                // 当授权开始日期为今天时，需要把历史数据授权给代理人
                // 将 Date 转换为 LocalDate
                LocalDate startDate = authUserDTO.getStartDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                LocalDate currentDate = LocalDate.now();
                // 比较两个 LocalDate 是否相等
                if (startDate.equals(currentDate)) {
                    grantAuthUser(saveUser);
                }

            });
        });

    }

    @Override
    public IPage<CgnciApprovalConfigRoleUserVO> authPage(CgnciApprovalConfigAuthQueryDTO queryDTO) {
        return this.baseMapper.authPage(queryDTO.toPage(), queryDTO);
    }

}
